package com.zmc.third.application.impl;

import com.alibaba.fastjson2.JSON;
import com.zmc.common.annotation.PreventRepeatSubmit;
import com.zmc.common.domain.freight.FreightCreateOrder;
import com.zmc.common.domain.resp.freight.FreightCreateOrderFeignResp;
import com.zmc.common.enums.SerialCodeEnum;
import com.zmc.common.utils.uuid.IdUtils;
import com.zmc.common.vo.OrderPayInfoVo;
import com.zmc.third.application.LogisticsService;
import com.zmc.third.exception.LogisticsException;
import com.zmc.third.feign.OrderFeignService;
import com.zmc.third.infrastructure.bean.logistics.*;
import com.zmc.third.infrastructure.bean.logistics.sf.SFRouteChildParam;
import com.zmc.third.infrastructure.bean.logistics.sf.SFRouteQuery;
import com.zmc.third.infrastructure.bean.logistics.sf.SFRouteResponse;
import com.zmc.third.infrastructure.bean.resp.FreightThirdCreateOrderResp;
import com.zmc.third.infrastructure.entity.LogisticsInfoEntity;
import com.zmc.third.infrastructure.enums.LogisticsEnum;
import com.zmc.third.infrastructure.service.LogisticsInfoService;
import com.zmc.third.utils.SFService;
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author：zmc
 * @Date：2025/1/14 14:57
 */
@Service
public class LogisticsServiceImpl implements LogisticsService {

    public static final Logger log = LoggerFactory.getLogger(LogisticsServiceImpl.class);

    @Autowired
    private LogisticsInfoService logisticsInfoService;

    @Autowired
    private OrderFeignService orderFeignService;

    @Autowired
    private SFService sfService;

    @Override
    @Transactional
    public FreightCreateOrderFeignResp createOrder(FreightCreateOrder freightCreateOrder) {
        FreightCreateOrderFeignResp feignResp = new FreightCreateOrderFeignResp();
        feignResp.setSuccess(false);
        String orderSn = freightCreateOrder.getOrderId();
        LogisticsInfoEntity info = logisticsInfoService.getByOrderSn(orderSn);
        if (info != null && !LogisticsEnum.LOGISTICS_CANCEL.getStatus().equals(info.getWmsStatus()) &&
                !LogisticsEnum.LOGISTICS_CREATE_FAIL.getStatus().equals(info.getWmsStatus())) {
            log.error("当前订单orderSn:{},正在派送中", orderSn);
            throw new LogisticsException("当前订单正在派送中");
        }
        RequestCreate en = constructorRequestCreate(freightCreateOrder);
        FreightThirdCreateOrderResp resp = sfService.createOrder(en);
        LogisticsInfoEntity entity = new LogisticsInfoEntity();
        entity.setOrderSn(orderSn);
        entity.setThirdOrderSn(en.getOrderId());
        entity.setResult(resp.getResult());
        if (resp.isSuccess()) {
            entity.setWmsOrderSn(resp.getWmsOrderId());
            entity.setWmsStatus(LogisticsEnum.LOGISTICS_WAIT.getStatus());
            feignResp.setSuccess(true);
            feignResp.setWmsOrderId(resp.getWmsOrderId());
        } else {
            //处理重复订单
            if (resp.isRepeatOrder()) {
                entity.setWmsStatus(LogisticsEnum.LOGISTICS_CREATE.getStatus());
            } else {
                log.error("创建订单失败，orderId:{}", orderSn);
                throw new LogisticsException("创建订单失败");
            }
        }
        logisticsInfoService.save(entity);
        return feignResp;
    }

    @Override
    public void cancel(String orderSn) {
        LogisticsInfoEntity info = logisticsInfoService.getByOrderSn(orderSn);
        if (info == null) {
            throw new LogisticsException("当前物流单不存在");
        }
        if (!LogisticsEnum.LOGISTICS_CREATE.getStatus().equals(info.getWmsStatus()) ||
                !LogisticsEnum.LOGISTICS_WAIT.getStatus().equals(info.getWmsStatus())) {
            throw new LogisticsException("当前物流单无法取消");
        }
        OrderConformCancelRequest request = new OrderConformCancelRequest();
        request.setSearchType(LogisticsEnum.LOGISTICS_QUERY_CANCEL.getStatus());
        request.setOrderId(orderSn);
        boolean success = sfService.cancel(request);
        if (success) {
            info.setWmsStatus(LogisticsEnum.LOGISTICS_CANCEL.getStatus());
        } else {
            info.setWmsStatus(LogisticsEnum.LOGISTICS_SENDING.getStatus());
        }
        logisticsInfoService.updateById(info);
    }

    @Override
    public BigDecimal queryPrice(PriceQuery query) {
        return sfService.queryPrice(query);
    }

    /**
     * todo 路由查询 正式环境每日允许最大查询次数为50w次，后期非特殊需求，需改为路由推送接口来获取数据
     * */
    @Override
    @PreventRepeatSubmit(key = "#orderSn", openSpEL = true)
    @Transactional
    @ShardingSphereTransactionType(TransactionType.BASE)
    public List<SFRouteChildParam> routeQuery(String orderSn) {
        LogisticsInfoEntity info = logisticsInfoService.getByOrderSn(orderSn);
        if (info == null) {
            throw new LogisticsException("当前物流订单不存在");
        }
        if (info.getRouteInfo() != null && info.getRouteLastUpdateTime().isEqual(LocalDate.now())) {
            return JSON.parseArray(info.getRouteInfo(), SFRouteChildParam.class);
        }
        SFRouteQuery query = new SFRouteQuery();
        List<String> list = new ArrayList<>();
        list.add(orderSn);
        query.setTrackingNumber(list);
        SFRouteResponse sfRouteResponse = sfService.routeQuery(query);
        List<SFRouteChildParam> routes = sfRouteResponse.getRouteResps().stream().filter(item -> item.getMailNo().equals(orderSn)).findFirst().orElseThrow(() -> new LogisticsException("获取物流路由信息异常")).getRoutes();
        boolean isSign = false;
        for (SFRouteChildParam param : routes) {
            String opCode = param.getOpCode();
            if (opCode.equals(LogisticsEnum.LOGISTICS_SIGN.getStatus()) ||
                    opCode.equals(LogisticsEnum.LOGISTICS_GET_SIGN.getStatus()) ||
                    opCode.equals(LogisticsEnum.LOGISTICS_THIRD_SIGN.getStatus())) {
                isSign = true;
                break;
            }
        }
        info.setRouteInfo(JSON.toJSONString(routes));
        info.setRouteLastUpdateTime(LocalDate.now());
        if (isSign) {
            info.setWmsStatus(LogisticsEnum.LOGISTICS_COMPLETE.getStatus());
            //更新订单状态
            OrderPayInfoVo vo = new OrderPayInfoVo();
            vo.setOrderNo(orderSn);
            orderFeignService.freightSignComplete(vo);
        }
        logisticsInfoService.updateById(info);
        return routes;
    }


    public RequestCreate constructorRequestCreate(FreightCreateOrder freightCreateOrder) {
        RequestCreate en = new RequestCreate();
        en.setOrderId(IdUtils.getBusinessCode(SerialCodeEnum.THIRD_WMS_NO.getCode()));
        List<CargoDetail> details = new ArrayList<>();
        CargoDetail detail = new CargoDetail();
        detail.setName(freightCreateOrder.getGoodName());
        detail.setCount(freightCreateOrder.getGoodCount());
        detail.setWeight(freightCreateOrder.getGoodWeight());
        details.add(detail);
        en.setCargoDetails(details);
        List<ContactInfo> contactInfoList = new ArrayList<>();
        ContactInfo sendInfo = new ContactInfo();
        sendInfo.setContactType(1);
        sendInfo.setMobile(freightCreateOrder.getSendPhone());
        sendInfo.setAddress(freightCreateOrder.getSendDetailAddress());
        sendInfo.setPostCode(freightCreateOrder.getSendPostCode());
        contactInfoList.add(sendInfo);
        ContactInfo acceptInfo = new ContactInfo();
        acceptInfo.setContactType(2);
        acceptInfo.setMobile(freightCreateOrder.getAcceptPhone());
        acceptInfo.setAddress(freightCreateOrder.getAcceptDetailAddress());
        acceptInfo.setPostCode(freightCreateOrder.getAcceptPostCode());
        contactInfoList.add(acceptInfo);
        en.setContactInfoList(contactInfoList);
        return en;
    }
}
